package model

import (
	"encoding/json"
	"fmt"
	"go_code/project01_basic/chapter15_qq/message"
	"go_code/project01_basic/chapter15_qq/server/utils"
	"net"
	"strconv"

	"github.com/gomodule/redigo/redis"
)

var (
	MyUserDao *UserDao
)

type UserDao struct {
	pool *redis.Pool
}

func NewUserDao(pool *redis.Pool) (userDao *UserDao) {
	return &UserDao{pool}
}

func (u *UserDao) Login(userId int, UserPwd string) (user *User, err error) {
	conn := u.pool.Get()
	defer conn.Close()
	user, err = u.GetUserById(conn, userId)
	if err != nil {
		return
	}
	if user.UserPwd != UserPwd {
		err = ErrorUPWD
		return
	}
	return
}

func (u *UserDao) Register(user *message.User) (err error) {
	conn := u.pool.Get()
	defer conn.Close()
	_, err = u.GetUserById(conn, user.UserId)
	if err == nil {
		err = ErrorUE
		return
	}
	data, err := json.Marshal(user)
	if err != nil {
		return
	}
	_, err = conn.Do("hset", "users", user.UserId, string(data))
	if err != nil {
		fmt.Println("register to redis err=", err)
		return
	}
	return
}

func (u *UserDao) GetUserById(conn redis.Conn, id int) (user *User, err error) {
	res, err := redis.String(conn.Do("hget", "users", id))
	if err != nil {
		if err == redis.ErrNil {
			err = ErrorUNE
		}
		return
	}
	user = &User{}
	err = json.Unmarshal([]byte(res), user)
	if err != nil {
		fmt.Println("redis res Unmarshal err=", err)
		return
	}
	return
}

func (u *UserDao) GetAllUsers() (res []int) {
	conn := u.pool.Get()
	defer conn.Close()
	r, err := redis.Strings(conn.Do("hkeys", "users"))
	if err != nil {
		fmt.Println(err)
		return nil
	}
	for _, v := range r {
		id, _ := strconv.Atoi(v)
		res = append(res, id)
	}
	return
}

func (u *UserDao) LeaveSmsSave(mes *message.Message, id int) (err error) {
	conn := u.pool.Get()
	defer conn.Close()
	data, err := json.Marshal(mes)
	if err != nil {
		return
	}
	people := "leaveSmsTo" + fmt.Sprint(id)
	_, err = conn.Do("LPUSH", people, string(data))
	return
}

func (u *UserDao) LeaveSmsPut(id int, c net.Conn) (err error) {
	conn := u.pool.Get()
	defer conn.Close()
	people := "leaveSmsTo" + fmt.Sprint(id)

	tf := &utils.Transfer{
		Conn: c,
	}

	for err != redis.ErrNil {
		data, err := redis.String(conn.Do("rpop", people))
		if err != nil {
			return err
		}
		var mes message.Message
		err = json.Unmarshal([]byte(data), &mes)
		if err != nil {
			return err
		}
		tf.Delivery(&mes)
	}
	return
}
